package cn.admin.configcenter.configservice.controller;

import cn.admin.configcenter.configservice.domain.ConfigInfo;
import cn.admin.configcenter.configservice.domain.Page;
import cn.admin.configcenter.configservice.domain.PageableContextResult;
import cn.admin.configcenter.configservice.service.ConfigSDKService;
import cn.admin.configcenter.configservice.service.ConfigServiceServerException;
import cn.admin.configcenter.configservice.util.JSONUtils;
import cn.admin.configcenter.configservice.util.RequestResponseUtil;
import cn.admin.configcenter.configservice.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@RestController
@RequestMapping({"/diamond-server","/config-center"})
public class ConfigServiceSDK {

	private static Logger LOG = LoggerFactory.getLogger(ConfigServiceSDK.class);

	@Autowired
	private ConfigSDKService configSDKService;

	@RequestMapping(
			params = {"method=listConfig"},
			value = {"/admin.do"},
			method = RequestMethod.GET)
	public String listConfig(@RequestParam(value = "dataId",required = false) String dataId,
	                         @RequestParam(value = "group",required = false) String group,
	                         @RequestParam(value = "srcIp",required = false) String srcIp,
	                         @RequestParam(value = "currentPage",required = false) Integer currentPage,
	                         @RequestParam(value = "pageSize",required = false) Integer pageSize) {

		LOG.info("request params : { dataId=" + dataId + ", group=" + group +
				", pageNo=" + currentPage + ", pageSize=" + pageSize + " }");

		PageableContextResult<ConfigInfo> result = this.processQuery(
				dataId,group,srcIp,null,currentPage,pageSize);
		String jsonString;
		try {
			jsonString = JSONUtils.serializeObject(result);
			return jsonString;
		} catch (Throwable e) {
			LOG.error("query  error with request params:  { dataId=" + dataId +
					", group=" + group + ", pageNo=" + currentPage + ", pageSize=" + pageSize + " }", e);
			throw new ConfigServiceServerException("query error : ", e);
		}
	}

    @RequestMapping(
            params = {"method=publishConfig"},
            value = {"/admin.do"},
            method = {RequestMethod.POST}
    )
	public String publishConfig(@RequestParam("dataId") String dataId,
                                @RequestParam("group") String group,
                                @RequestParam("content") String content,
                                @RequestParam("srcIp") String srcIp,
                                @RequestParam(value = "appName",required = false) String appName) throws Exception {
	    return this.createOrUpdate(dataId,group,content,srcIp,appName);
    }


    @RequestMapping(
            params = {"method=modifyConfig"},
            value = {"/admin.do"},
            method = {RequestMethod.POST}
    )
    public String modifyConfig(@RequestParam("dataId") String dataId,
                               @RequestParam("group") String group,
                               @RequestParam("content") String content,
                               @RequestParam("srcIp") String srcIp,
                               @RequestParam(value = "appName",required = false) String appName) throws Exception {
	    return this.createOrUpdate(dataId,group,content,srcIp,appName);
    }

    @RequestMapping(
            params = {"method=removeConfig"},
            value = {"/admin.do"},
            method = {RequestMethod.POST}
    )
    public String removeConfig(HttpServletRequest request,
                               @RequestParam("dataId") String dataId,
                               @RequestParam("group") String group,
                               @RequestParam("content") String content,
                               @RequestParam("srcIp") String srcIp,
                               @RequestParam(value = "appName",required = false) String appName) throws IOException {
	    LOG.debug("request params : { dataId=" + dataId + ", group=" + group + ", appName=" + appName + " }");
	    String srcOperator = RequestResponseUtil.getRemoteIp(request);
	    this.configSDKService.removeConfig(dataId,group,srcIp);
	    LOG.info("sdk config removed : dataId=" + dataId + ", group=" + group +
                ", appName=" + appName + " by " + srcOperator);
        PageableContextResult<ConfigInfo> response = new PageableContextResult<>();
        response.setSuccess(true);
        response.setCode(HttpStatus.OK.value());
        response.setMessage("operate success");
        return JSONUtils.serializeObject(response);
    }

    @RequestMapping(
            params = {"method=listPubConfig"},
            value = {"/admin.do"},
            method = {RequestMethod.GET}
    )
    public String listPublishedConfig(@RequestParam(value = "clientIp",required = false) String clientIp,
                                      @RequestParam(value = "currentPage",required = false) Integer pageNo,
                                      @RequestParam(value = "pageSize",required = false) Integer pageSize) {
        LOG.info("request params : { clientIp=" + clientIp + ", currentPage=" + pageNo +
                ", pageSize=" + pageSize + " }");
        PageableContextResult<ConfigInfo> response = new PageableContextResult<>();
        Page<ConfigInfo> pageableConfigInfos = this.configSDKService.listPublishedConfigByIp(pageNo, pageSize,
                clientIp);
        response.setData(pageableConfigInfos);
        response.setSuccess(true);
        response.setCode(HttpStatus.OK.value());
        response.setMessage("query config list success");
        String jsonString;

        try {
            jsonString = JSONUtils.serializeObject(response);
            System.out.println(jsonString);
            return jsonString;
        } catch (Throwable e) {
            LOG.error("query  error with request params:  { clientIp=" + clientIp + ", currentPage=" + pageNo +
                    ", pageSize=" + pageSize + " }", e);
            throw new ConfigServiceServerException("query error : ", e);
        }
    }

    @RequestMapping(
            params = {"method=listSubConfig"},
            value = {"/admin.do"},
            method = {RequestMethod.GET}
    )
    public String listSubscribedConfig(@RequestParam(value = "clientIp",required = false) String clientIp,
                                       @RequestParam(value = "currentPage",required = false) Integer pageNo,
                                       @RequestParam(value = "pageSize",required = false) Integer pageSize) {
        LOG.info("request params : { clientIp=" + clientIp + ", currentPage=" + pageNo + ", pageSize=" + pageSize + " }");
        PageableContextResult<ConfigInfo> response = new PageableContextResult<>();
        Page<ConfigInfo> pageableConfigInfos = this.configSDKService.listSubscribedConfigByIp(pageNo, pageSize,
                clientIp);
        response.setData(pageableConfigInfos);
        response.setSuccess(true);
        response.setCode(HttpStatus.OK.value());
        response.setMessage("query config list success");
        String jsonString;

        try {
            jsonString = JSONUtils.serializeObject(response);
            return jsonString;
        } catch (Throwable e) {
            LOG.error("query  error with request params:  { clientIp=" + clientIp +
                    ", currentPage=" + pageNo + ", pageSize=" + pageSize + " }", e);
            throw new ConfigServiceServerException("query error : ", e);
        }
    }

	private String createOrUpdate(String dataId,String group,String content,String srcIp,
                                  String appName) throws Exception {
	    LOG.info("request params : { dataId=" + dataId + ", group=" + group +
                ", srcIp=" + srcIp + ", content=" + content + ", appName=" + appName + " }");
	    boolean result = this.configSDKService.createOrUpdateConfig(dataId,group,content,srcIp,appName);
	    PageableContextResult<ConfigInfo> response = new PageableContextResult<>();
	    response.setSuccess(result);
	    if (result) {
	        response.setCode(HttpStatus.OK.value());
	        response.setMessage("operate success");
        } else {
	        response.setCode(500);
	        response.setMessage("operate failed");
        }
        return JSONUtils.serializeObject(response);
    }

	private PageableContextResult<ConfigInfo> processQuery(String dataIdPattern, String groupNamePattern,
	                                                       String srcIpPattern, String contentPattern,
	                                                       int currentPage, int sizeOfPerPage) {

		PageableContextResult<ConfigInfo> response = new PageableContextResult<>();
		Page<ConfigInfo> pageableConfigInfos;
		if (StringUtils.isBlank(dataIdPattern) && StringUtils.isBlank(groupNamePattern)
				&& StringUtils.isBlank(contentPattern) && StringUtils.isBlank(srcIpPattern)) {
			pageableConfigInfos = this.configSDKService.findConfigInfo(currentPage, sizeOfPerPage,
					groupNamePattern, dataIdPattern);
		} else {
			pageableConfigInfos = this.configSDKService.listConfigLike(currentPage, sizeOfPerPage,
					groupNamePattern, dataIdPattern, contentPattern, srcIpPattern);
		}

		response.setData(pageableConfigInfos);
		response.setSuccess(true);
		response.setCode(HttpStatus.OK.value());
		response.setMessage("query config list success");
		return response;
	}


}
